ifndef OBJECTS
$(error OBJECTS variable not defined)
endif

ifndef MAIN_SRC
$(error MAIN_SRC variable not defined)
endif

ifndef COMPILE_TYPE
	COMPILE_TYPE := dev
endif

ifndef BIN_DIR 
	BIN_DIR := ./bin
endif

OBJ_DIR := obj
BUILD_DIR := $(BIN_DIR)/$(OBJ_DIR)/$(COMPILE_TYPE)
# Create a list of dependant .o's in the .obj/build_type dir
DEPS_OBJECTS:= $(patsubst ./../$(OBJ_DIR)/%, ./../$(OBJ_DIR)/$(COMPILE_TYPE)/%,$(DEPS_OBJECTS))

# Different release types
ifeq ($(COMPILE_TYPE), dev)
	# No optimization, inclde debug symbols, compile objs for unit testing
	CXXFLAGS += -O0 -ansi -pedantic -Wall -g3 -DTEST_VIRTUAL=virtual
endif
ifeq ($(COMPILE_TYPE), code_coverage)
	# Use to create coverage tests
	CXXFLAGS += -O0 -ansi -pedantic -Wall -g3 -DTEST_VIRTUAL=virtual -fprofile-arcs -ftest-coverage --coverage
	LDFLAG += --coverage -lgcov
endif
ifeq ($(COMPILE_TYPE), release)
	# Release binary, min debug symbols
	CXXFLAGS += -O2 -ansi -pedantic -Wall -g1 -DTEST_VIRTUAL=
endif


OBJECTS := $(addprefix $(BUILD_DIR)/,$(OBJECTS))
MAIN_OBJ := $(addprefix $(BUILD_DIR)/, $(patsubst %.cpp,%.o,$(MAIN_SRC)))
DEPENDS := $(patsubst %.o,%.P,$(OBJECTS)) $(patsubst %.o,%.P,$(COBJECTS))
TEST_SRCS := $(patsubst ./%, %, $(shell find -L|grep -v svn|egrep "_Test\.cpp$$" ) )
TEST_BINS := $(addprefix ./$(BIN_DIR)/, $(patsubst %.cpp, %, $(TEST_SRCS)) )


# Dependency directoy
df=$(BUILD_DIR)/$(*D)/$(*F)

$(OBJECTS): $(BUILD_DIR)/%.o: %.cpp
	@mkdir -p $(BUILD_DIR)/$(*D)
	$(COMPILE.cpp) -MD -o $@ $< 
	@cp $(df).d $(df).P; \
	sed -e 's/#.*//' -e 's/^[^:]*: *//' -e 's/ *\\$$//' \
		-e '/^$$/ d' -e 's/$$/ :/' < $(df).d >> $(df).P; \
	rm -f $(df).d

$(MAIN_OBJ): $(MAIN_SRC)
	$(COMPILE.cpp) -MD -o $@ $< 

# Binary name depends on BIN_DIR/BIN_NAME, so the call to create BIN can
# be forwarded to BIN_DIR/BIN_NAME
$(BINARY): $(BIN_DIR)/$(BINARY)
$(BIN_DIR)/$(BINARY): $(OBJECTS) $(DEPS_OBJECTS) $(MAIN_OBJ)
	@mkdir -p $(BIN_DIR)
	@# Workaround for a linker bug: if the libs are not 
	@# at the end it won't link (something to do with how the linker
	@# lists the dependencies... too long for a comment, rtfm
	g++ $(CXXFLAGS) $^ -o $(BIN_DIR)/$@ $(LDFLAGS)
	@#$(LINK.cpp) $^ -o $@ 

$(BIN_DIR)/%_Test: $(patsubst $(BIN_DIR)/%, %, %_Test.cpp ) %.cpp %.h
	@echo "Making $@"
	@mkdir -p $(shell dirname $@)
	g++ $(CXXFLAGS) -g3 -O0 $< -o $@ -lpthread -lgtest_main -lgmock $(OBJECTS) $(LDFLAGS)


.PHONY: clean test coverage_report pretty

clean:
	rm -rf $(BIN_DIR)/$(OBJ_DIR) $(BIN_DIR)/$(BINARY) $(MAIN_OBJ)
	for TEST in $(TEST_BINS); do \
		rm -rf "$$TEST"; \
	done

test: $(TEST_SRCS)
	@for TEST in $(TEST_BINS); do \
		make "$$TEST"; \
		echo "Execute $(TEST)"; \
		./$$TEST; \
	done

coverage_report:
	# Reset code coverage counters and clean up previous reports
	rm -rf coverage_report
	lcov --zerocounters --directory .
	$(MAKE) COMPILE_TYPE=code_coverage &&\
	$(MAKE) COMPILE_TYPE=code_coverage test
	lcov --capture --directory $(BIN_DIR)/$(OBJ_DIR)/code_coverage --base-directory . -o salida.out &&\
	lcov --remove salida.out "*usr/include*" -o salida.out &&\
	genhtml -o coverage_report salida.out
	rm salida.out

pretty:
	find -L|egrep '\.(cpp|h|hh)$$'|egrep -v 'svn|_Test.cpp$$' | xargs astyle --convert-tabs -bSKpUH -k1 

tasks:
	grep -nri TODO *|egrep -v 'svn|Binary file'

-include $(DEPENDS)


